﻿using System.Linq;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using KZ.Exception;
using KZ.Lottery.Entities;
using KZ.Lottery.Resources;
using KZ.Utilities;

namespace KZ.Lottery.DAL
{
    public class RuleDetailGroupDAL
    {
        private static RuleDetailGroup CreateRuleDetailGroupFromReader(SqlDataReader reader)
        {
            RuleDetailGroup ruleDetailGroup = new RuleDetailGroup
            {
                RuleDetailID = Utility.StringParse(reader[RuleDetailGroupColumns.RuleDetailID.ToString()]),
                RuleIsActived = Utility.BoolParse(reader[RuleDetailGroupColumns.RuleIsActived.ToString()]),
                GroupID = Utility.StringParse(reader[RuleDetailGroupColumns.GroupID.ToString()]),
                HeadDay = Utility.IntParse(reader[RuleDetailGroupColumns.HeadDay.ToString()]),
                TailDay = Utility.IntParse(reader[RuleDetailGroupColumns.TailDay.ToString()]),
                FirstDayAmount = Utility.DecimalParse(reader[RuleDetailGroupColumns.FirstDayAmount.ToString()]),
                HeadAmount = Utility.DecimalParse(reader[RuleDetailGroupColumns.HeadAmount.ToString()]),
                TailAmount = Utility.DecimalParse(reader[RuleDetailGroupColumns.TailAmount.ToString()]),
            };

            ruleDetailGroup.HeadTempAmount = ruleDetailGroup.HeadAmount;
            ruleDetailGroup.TailTempAmount = ruleDetailGroup.TailAmount;
            ruleDetailGroup.IsGroupHead = false;
            ruleDetailGroup.IsGroupTail = false;

            ruleDetailGroup.Group = new Group
            {
                GroupID = ruleDetailGroup.GroupID,
                Order = Utility.IntParse(reader[GroupColumns.Order.ToString()]),
            };

            return ruleDetailGroup;
        }

        public static List<RuleDetailGroup> GetRuleDetailGroupList(string ruleDetailID)
        {
            try
            {
                List<RuleDetailGroup> ruleDetailGroupList = new List<RuleDetailGroup>();

                DataAccessHelper.SqlCmd.Parameters.Add("RuleDetailID", SqlDbType.NVarChar).Value = ruleDetailID;
                using (SqlDataReader reader = DataAccessHelper.ExecuteQuery(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupGetList))
                {
                    while (reader.Read())
                    {
                        ruleDetailGroupList.Add(CreateRuleDetailGroupFromReader(reader));
                    }
                }

                return ruleDetailGroupList;
            }
            catch (SqlException ex)
            {
                Log.LogEx("GetRuleDetailGroupList", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_GET);
            }
        }

        /// <summary>
        /// Has transaction
        /// </summary>
        public static List<RuleDetailGroup> GetRuleDetailGroupList2(string ruleDetailID)
        {
            try
            {
                List<RuleDetailGroup> ruleDetailGroupList = new List<RuleDetailGroup>();

                DataAccessHelper.SqlCmd.Parameters.Add("RuleDetailID", SqlDbType.NVarChar).Value = ruleDetailID;
                using (SqlDataReader reader = DataAccessHelper.ExecuteQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupGetList))
                {
                    while (reader.Read())
                    {
                        ruleDetailGroupList.Add(CreateRuleDetailGroupFromReader(reader));
                    }
                }

                return ruleDetailGroupList;
            }
            catch (SqlException ex)
            {
                Log.LogEx("GetRuleDetailGroupList", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_GET);
            }
        }

        public static RuleDetailGroup ComputeRuleDetailGroupHeadWinOrNot(RuleDetailGroup rdGroup, ref List<RuleDetailGroup> rdgList, ref Entities.Report report, ref decimal headWinAmount,
            int maxDay, Result result, List<GroupValue> gvList, List<SettingValue> settingValueList)
        {
            //// group win lottery
            //// reset to first day
            if (gvList.Exists(gv => gv.GroupID == rdGroup.GroupID && gv.Value == result.Head))
            {
                if (rdGroup.RuleIsActived)
                {
                    headWinAmount += settingValueList[rdGroup.HeadDay - 1].Value - rdGroup.FirstDayAmount;
                }
                report.HeadWinAmount += (settingValueList[rdGroup.HeadDay - 1].Value - rdGroup.FirstDayAmount) * Global.WinRate;
                rdGroup.HeadDay = 1;
                rdGroup.HeadAmount = settingValueList[0].Value;
                GroupHighestDayDAL.UpdateGroupHighestDay(rdGroup.GroupID, rdGroup.RuleDetailID);
            }
            else
            {
                rdGroup.HeadDay = rdGroup.HeadDay + 1 > maxDay ? 1 : rdGroup.HeadDay + 1;
                rdGroup.HeadAmount = settingValueList[rdGroup.HeadDay - 1].Value;
                GroupHighestDayDAL.InsertGroupHighestDay(rdGroup.GroupID, rdGroup.RuleDetailID);
                //if (rdGroup.HeadDay > Global.GroupDay)
                //{
                //    rdGroup.HeadAmount *= Global.Rate;
                //}
                //else
                //{
                //    rdGroup.HeadAmount = settingValueList[rdGroup.HeadDay - 1].Value;
                //}

                //if (rdGroup.HeadDay == Global.GroupDay || ((rdGroup.HeadDay - Global.GroupDay) % (Global.Loop - 1) == 0 && rdGroup.HeadDay > Global.GroupDay))
                //{
                //    List<GroupGroup> ggList = GroupGroupDAL.GetGroupGroupByGroupID(rdGroup.GroupID);
                //    int numberOfGroup = ggList.GroupBy(g => g.GroupCode).ToList().Count;

                //    RuleDetailGroupDAL rdgDAL = new RuleDetailGroupDAL();
                //    for (int i = 0; i < numberOfGroup; i++)
                //    {
                //        List<GroupGroup> ggTemp = new List<GroupGroup>(ggList.Where(gg => gg.GroupCode == ggList[0].GroupCode));
                //        ggList.RemoveAll(gg => gg.GroupCode == ggTemp[0].GroupCode);

                //        decimal amount = settingValueList[rdGroup.HeadDay - 1].Value;
                //        List<RuleDetailGroup> rdgTemp = new List<RuleDetailGroup>();
                //        foreach (GroupGroup gg in ggTemp)
                //        {
                //            RuleDetailGroup rdg = rdgList.SingleOrDefault(r => r.GroupID == gg.GroupID);
                //            rdgTemp.Add(rdg);

                //            //// check group, if win reset to 1 else increase 1 day
                //            if (gvList.Exists(gv => gv.GroupID == rdg.GroupID && gv.Value == result.Head))
                //            {
                //                amount += settingValueList[0].Value;
                //            }
                //            else
                //            {
                //                amount += settingValueList[rdg.HeadDay].Value;
                //            }
                //            rdg.HeadDay = rdGroup.HeadDay;
                //            rdg.IsGroupHead = true;
                //        }

                //        amount /= (ggTemp.Count + 1);
                //        rdGroup.HeadAmount = amount;
                //        foreach (RuleDetailGroup rdg in rdgTemp)
                //        {
                //            rdg.HeadAmount = amount;
                //            rdgDAL.UpdateRuleDetailGroupHead(rdg);
                //        }
                //    }
                //}
            }

            return rdGroup;
        }

        public static RuleDetailGroup ComputeRuleDetailGroupTailWinOrNot(RuleDetailGroup rdGroup, ref List<RuleDetailGroup> rdgList, ref Entities.Report report, ref decimal tailWinAmount,
           int maxDay, Result result, List<GroupValue> gvList, List<SettingValue> settingValueList)
        {
            //// group win lottery
            //// reset to first day
            if (gvList.Exists(gv => gv.GroupID == rdGroup.GroupID && gv.Value == result.Tail))
            {
                if (rdGroup.RuleIsActived)
                {
                    tailWinAmount += settingValueList[rdGroup.TailDay - 1].Value - rdGroup.FirstDayAmount;
                }
                report.TailWinAmount += (settingValueList[rdGroup.TailDay - 1].Value - rdGroup.FirstDayAmount) * Global.WinRate;
                rdGroup.TailDay = 1;
                rdGroup.TailAmount = settingValueList[0].Value;
                GroupHighestDayDAL.InsertGroupHighestDay(rdGroup.GroupID, rdGroup.RuleDetailID);
            }
            else
            {
                rdGroup.TailDay = rdGroup.TailDay + 1 > maxDay ? 1 : rdGroup.TailDay + 1;
                rdGroup.TailAmount = settingValueList[rdGroup.TailDay - 1].Value;
                GroupHighestDayDAL.InsertGroupHighestDay(rdGroup.GroupID, rdGroup.RuleDetailID);
                //if (rdGroup.TailDay > Global.GroupDay)
                //{
                //    rdGroup.TailAmount *= Global.Rate;
                //}
                //else
                //{
                //    rdGroup.TailAmount = settingValueList[rdGroup.TailDay - 1].Value;
                //}

                //if (rdGroup.TailDay == Global.GroupDay || ((rdGroup.TailDay - Global.GroupDay) % (Global.Loop - 1) == 0 && rdGroup.TailDay > Global.GroupDay))
                //{
                //    List<GroupGroup> ggList = GroupGroupDAL.GetGroupGroupByGroupID(rdGroup.GroupID);
                //    int numberOfGroup = ggList.GroupBy(g => g.GroupCode).ToList().Count;

                //    RuleDetailGroupDAL rdgDAL = new RuleDetailGroupDAL();
                //    for (int i = 0; i < numberOfGroup; i++)
                //    {
                //        List<GroupGroup> ggTemp = new List<GroupGroup>(ggList.Where(gg => gg.GroupCode == ggList[0].GroupCode));
                //        ggList.RemoveAll(gg => gg.GroupCode == ggTemp[0].GroupCode);

                //        decimal amount = settingValueList[rdGroup.TailDay - 1].Value;
                //        List<RuleDetailGroup> rdgTemp = new List<RuleDetailGroup>();
                //        foreach (GroupGroup gg in ggTemp)
                //        {
                //            RuleDetailGroup rdg = rdgList.SingleOrDefault(r => r.GroupID == gg.GroupID);
                //            rdgTemp.Add(rdg);

                //            //// check group, if win reset to 1 else increase 1 day
                //            if (gvList.Exists(gv => gv.GroupID == rdg.GroupID && gv.Value == result.Tail))
                //            {
                //                amount += settingValueList[0].Value;
                //            }
                //            else
                //            {
                //                amount += settingValueList[rdg.TailDay].Value;
                //            }
                //            rdg.TailDay = rdGroup.TailDay;
                //            rdg.IsGroupHead = false;
                //        }

                //        amount /= (ggTemp.Count + 1);
                //        rdGroup.TailAmount = amount;
                //        foreach (RuleDetailGroup rdg in rdgTemp)
                //        {
                //            rdg.TailAmount = amount;
                //            rdgDAL.UpdateRuleDetailGroupTail(rdg);
                //        }
                //    }
                //}
            }

            return rdGroup;
        }

        public bool InsertRuleDetailGroup(RuleDetailGroup ruleDetailGroup)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleDetailID", SqlDbType.NVarChar).Value = ruleDetailGroup.RuleDetailID;
                DataAccessHelper.SqlCmd.Parameters.Add("GroupID", SqlDbType.NVarChar).Value = ruleDetailGroup.GroupID;
                DataAccessHelper.SqlCmd.Parameters.Add("HeadDay", SqlDbType.Int).Value = ruleDetailGroup.HeadDay;
                DataAccessHelper.SqlCmd.Parameters.Add("TailDay", SqlDbType.Int).Value = ruleDetailGroup.TailDay;
                DataAccessHelper.SqlCmd.Parameters.Add("FirstDayAmount", SqlDbType.Decimal).Value = ruleDetailGroup.FirstDayAmount;
                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupInsert) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_INSERT);
            }
            catch (SqlException ex)
            {
                Log.LogEx("InsertRuleDetailGroup", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_INSERT);
            }
        }

        public bool UpdateRuleDetailGroupHead(RuleDetailGroup ruleDetailGroup)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleDetailID", SqlDbType.NVarChar).Value = ruleDetailGroup.RuleDetailID;
                DataAccessHelper.SqlCmd.Parameters.Add("GroupID", SqlDbType.NVarChar).Value = ruleDetailGroup.GroupID;
                DataAccessHelper.SqlCmd.Parameters.Add("HeadDay", SqlDbType.Int).Value = ruleDetailGroup.HeadDay;
                DataAccessHelper.SqlCmd.Parameters.Add("HeadAmount", SqlDbType.Decimal).Value = ruleDetailGroup.HeadAmount;

                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupUpdateHead) > 0)
                {
                    return true;
                }
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("UpdateRuleDetailGroup", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
        }

        public bool UpdateRuleDetailGroupTail(RuleDetailGroup ruleDetailGroup)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleDetailID", SqlDbType.NVarChar).Value = ruleDetailGroup.RuleDetailID;
                DataAccessHelper.SqlCmd.Parameters.Add("GroupID", SqlDbType.NVarChar).Value = ruleDetailGroup.GroupID;
                DataAccessHelper.SqlCmd.Parameters.Add("TailDay", SqlDbType.Int).Value = ruleDetailGroup.TailDay;
                DataAccessHelper.SqlCmd.Parameters.Add("TailAmount", SqlDbType.Decimal).Value = ruleDetailGroup.TailAmount;

                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupUpdateTail) > 0)
                {
                    return true;
                }
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("UpdateRuleDetailGroup", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
        }

        public bool UpdateRuleDetailGroupFirstDay()
        {
            try
            {
                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleDetailGroupUpdateFirstDay) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("UpdateRuleDetailGroup", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULEDETAILGROUP_UPDATE);
            }
        }
    }
}